package control;

import java.util.Vector;

import utils.DataFormat;
import basic.Date;
import basic.Transaction;
import domain.Category;
import domain.Expense;
import domain.FamilyMember;
import domain.Income;
import domain.Loan;
import domain.PaymentMethod;
import enums.LoanState;

//@author A0097788Y
public class Search {

	private ExpenseManager _expense;
	private IncomeManager _income;
	private LoanManager _loan;
	private CategoryManager _category;
	private MemberManager _member;
	private PaymentMethodManager _payment;

	//the id lists below must be initialize and generated via toVector method
	private Vector<Integer> _expenseIdList;
	private Vector<Integer> _incomeIdList;
	private Vector<Integer> _loanIdList;

	/**
	 * 
	 * @param em
	 * @param im
	 * @param lm
	 * @param cm
	 * @param mm
	 * @param pm
	 */
	public Search(ExpenseManager em, IncomeManager im, LoanManager lm, CategoryManager cm, MemberManager mm, PaymentMethodManager pm){
		_expense = em;
		_income = im;
		_loan = lm;
		_category = cm;
		_member = mm;
		_payment = pm;
	}

	/**
	 * @param em
	 * @param cm
	 * @param mm
	 * @param pm
	 */
	public Search(ExpenseManager em, CategoryManager cm, MemberManager mm, PaymentMethodManager pm){
		_expense = em;
		_category = cm;
		_member = mm;
		_payment = pm;
	}
	public Search(ExpenseManager em, CategoryManager cm){
		_expense = em;
		_category = cm;
	}

	/**
	 * @param im
	 */
	public Search (IncomeManager im){
		_income = im;
	}

	/**
	 * @param lm
	 * @param mm TODO
	 * @param mm
	 */
	public Search (LoanManager lm, MemberManager mm) {
		_loan = lm;
	}


	/**
	 * 
	 * @return Vector of expense IDs
	 * @Precondition 
	 * @Postcondition 
	 */
	public Vector<Integer> getExpenseIdList()
	{
		return _expenseIdList;
	}
	/**
	 * 
	 * @return Vector of income IDs
	 * @Precondition 
	 * @Postcondition 
	 */
	public Vector<Integer> getIncomeIdList()
	{
		return _incomeIdList;
	}

	/**
	 * 
	 * @return Vector of loan IDs
	 * @Precondition 
	 * @Postcondition 
	 */
	public Vector<Integer> getLoanIdList() {
		return _loanIdList;
	}

	/**
	 * Get expense column names
	 * @return Vector 
	 * @Precondition 
	 * @Postcondition returns Strings containing the headers for "Expense" in View Budget
	 */
	public static Vector<String> getToExpenseVectorColName()
	{
		Vector<String> expenseColName = new Vector<String>();
		expenseColName.add("Category");
		expenseColName.add("Name");
		expenseColName.add("Base Amount");
		expenseColName.add("Paid To");
		expenseColName.add("Payment");
		expenseColName.add("Frequency");
		expenseColName.add("Total Amount");
		expenseColName.add("Created Date");
		expenseColName.add("Last Update");
		expenseColName.add("Member");
		return expenseColName;
	}
	/**
	 * Get income column names
	 * @return Vector 
	 * @Precondition 
	 * @Postcondition returns Strings containing the headers for "Income" in View Budget
	 */
	public static Vector<String> getToIncomeVectorColName()
	{
		Vector<String> incomeColName = new Vector<String>();
		incomeColName.add("Name");
		incomeColName.add("Base Amount");
		incomeColName.add("Payer");
		incomeColName.add("Frequency");
		incomeColName.add("Total Amount");
		incomeColName.add("Created Date");
		incomeColName.add("Last Update");
		incomeColName.add("Member");
		return incomeColName;
	}
	/**
	 * Get loan column names
	 * @return Vector 
	 * @Precondition 
	 * @Postcondition returns Strings containing the headers for "Loan" in View Budget
	 */
	public static Vector<String> getToLoanVectorColName()
	{
		Vector<String> loanColName = new Vector<String>();
		loanColName.add("Name");
		loanColName.add("Base Amount");
		loanColName.add("Total Amount");
		loanColName.add("Net Interest Gain");
		loanColName.add("Loan State");
		loanColName.add("Created Date");
		loanColName.add("Last Update");
		loanColName.add("Party Involved");
		loanColName.add("Member");
		loanColName.add("Interest Rate");
		loanColName.add("Due Date");
		loanColName.add("Months Left");
		loanColName.add("Monthly Payment");
		return loanColName;
	}
	/**
	 * Get "All" column names
	 * @return Vector 
	 * @Precondition 
	 * @Postcondition returns Strings containing the headers for "All" in View Budget
	 */
	public static Vector<String> getToAllVectorColName()
	{
		Vector<String> allColName = new Vector<String>();
		allColName.add("Name");
		allColName.add("Type");
		allColName.add("Amount");
		allColName.add("Date");
		allColName.add("Member");
		return allColName;
	}

	/**
	 * 
	 * @param em
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set(ExpenseManager em){
		_expense = em;
	}
	/**
	 * 
	 * @param im
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set(IncomeManager im){
		_income = im;
	}
	/**
	 * 
	 * @param lm
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set(LoanManager lm){
		_loan = lm;
	}
	/**
	 * 
	 * @param cm
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set(CategoryManager cm){
		_category = cm;
	}
	/**
	 * 
	 * @return Vector containing all expenses
	 * @Precondition expense manager is updated
	 * @Postcondition 
	 */
	public Vector toExpenseVector(){ 
		Vector<Vector> allExpenses = new Vector<Vector>();
		_expenseIdList = new Vector<Integer>();
		for(Expense xpn : _expense.getList())
		{
			Vector entry = new Vector();
			entry.add(_category.get(xpn.get_category()).get_name());
			entry.add(xpn.get_name());
			entry.add("$" + DataFormat.returnTwoDecimals(xpn.get_amount()));
			entry.add(xpn.get_partyInvolved());
			entry.add(xpn.get_paymentMethod());
			entry.add(xpn.get_frequency());
			entry.add("$" + DataFormat.returnTwoDecimals(xpn.get_totalAmount()));
			entry.add(xpn.get_date());
			entry.add(xpn.get_lastUpdateDate());
			entry.add(xpn.get_byMem());
			_expenseIdList.add(xpn.get_id());
			allExpenses.add(entry);
		}
		return allExpenses;
	}

	/**
	 * 
	 * @return Vector containing all incomes
	 * @Precondition income manager is updated
	 * @Postcondition 
	 */
	public Vector toIncomeVector(){ 
		Vector<Vector> allIncome = new Vector<Vector>();
		_incomeIdList = new Vector<Integer>();
		for(Income income : _income.getList())
		{
			Vector entry = new Vector();
			entry.add(income.get_name());
			entry.add("$" + DataFormat.returnTwoDecimals(income.get_amount()));
			entry.add(income.get_partyInvolved());
			entry.add(income.get_frequency());
			entry.add("$" + DataFormat.returnTwoDecimals(income.get_totalAmount()));
			entry.add(income.get_date());
			entry.add(income.get_lastUpdateDate());
			entry.add(income.get_byMem());
			_incomeIdList.add(income.get_id());
			allIncome.add(entry);
		}
		return allIncome;
	}

	/**
	 * 
	 * @return Vector containing all loans
	 * @Precondition loan manager is updated
	 * @Postcondition 
	 */
	public Vector toLoanVector(){ 
		Vector<Vector> allLoans = new Vector<Vector>();
		_loanIdList = new Vector<Integer>();
		for(Loan loan : _loan.getList())
		{
			Vector entry = new Vector();
			entry.add(loan.get_name());
			entry.add("$" + DataFormat.returnTwoDecimals(loan.get_amount()));
			entry.add("$" + DataFormat.returnTwoDecimals(loan.get_totalAmount()));

			// Set gainFromInterest value in proper format depending on whether or not
			// The value is positive, negative, or 0
			if (loan.get_gainFromInterest() > 0)
				entry.add("$" + DataFormat.returnTwoDecimals(loan.get_gainFromInterest()));
			else if (loan.get_gainFromInterest() < 0)
				entry.add("-$" + DataFormat.returnTwoDecimals(Math.abs(loan.get_gainFromInterest())));
			else
				entry.add("$" + DataFormat.returnTwoDecimals(0));
			entry.add(loan.get_loanState());
			entry.add(loan.get_date());
			entry.add(loan.get_lastUpdateDate());
			entry.add(loan.get_partyInvolved());
			entry.add(loan.get_byMem());
			entry.add(DataFormat.returnTwoDecimals(loan.get_interestRate()) + "%");
			entry.add(loan.get_dueDate());
			entry.add(loan.get_monthsLeft());
			entry.add("$" + DataFormat.returnTwoDecimals(loan.get_paymentPerMonth()));

			_loanIdList.add(loan.get_id());
			allLoans.add(entry);
		}
		return allLoans;
	}

	/**
	 * 
	 * @return Vector containing all transactions
	 * @Precondition expense, income and loan manager is updated
	 * @Postcondition 
	 */
	public Vector toAllVector(){ 
		Vector<Vector> all = new Vector<Vector>();
		String prefix = new String("-");
		String loanType = new String();
		_expenseIdList = new Vector<Integer>();
		for(Expense xpn : _expense.getList())
		{
			Vector entry = new Vector();
			entry.add(xpn.get_name());
			entry.add("Expense");
			entry.add(prefix+"$"+DataFormat.returnTwoDecimals(xpn.get_amount()));
			entry.add(xpn.get_date());
			entry.add(xpn.get_byMem());
			_expenseIdList.add(xpn.get_id());
			all.add(entry);
		}

		prefix = "+";
		_incomeIdList = new Vector<Integer>();
		for(Income income : _income.getList())
		{
			Vector entry = new Vector();
			entry.add(income.get_name());
			entry.add("Income");
			entry.add(prefix+"$"+DataFormat.returnTwoDecimals(income.get_amount()));
			entry.add(income.get_date());
			entry.add(income.get_byMem());
			_incomeIdList.add(income.get_id());
			all.add(entry);
		}

		_loanIdList = new Vector<Integer>();
		for(Loan loan : _loan.getList())
		{
			Vector entry = new Vector();
			entry.add(loan.get_name());
			switch(loan.get_loanState()){
			case BORROWED:
				prefix = "-";
				loanType = LoanState.BORROWED.name();
				break;
			case LENT:
				prefix = "+";
				loanType = LoanState.LENT.name();
				break;
			case INVESTMENT:
				prefix = "+";
				loanType = LoanState.INVESTMENT.name();
			}
			entry.add("Loan, "+loan.get_loanState());
			entry.add(prefix+"$"+DataFormat.returnTwoDecimals(loan.get_amount()));
			entry.add(loan.get_date());
			entry.add(loan.get_byMem());
			_loanIdList.add(loan.get_id());
			all.add(entry);
		}
		return all;
	}

	/**
	 * 
	 * @param mem
	 * @return Vector containing expenses matching mem
	 * @Precondition updated managers
	 * @Postcondition 
	 */
	public Vector findExpenseByMem(FamilyMember mem){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Expense xpn : _expense.getList())
		{
			if (xpn.get_byMem().isSame(mem)){
				allExpenses.add(addExpense(xpn));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param mem
	 * @return Vector containing incomes matching mem
	 * @Precondition updated managers
	 * @Postcondition 
	 */
	public Vector findIncomeByMem(FamilyMember mem){
		Vector<Vector> allIncome = new Vector<Vector>();
		for(Income xpn : _income.getList())
		{
			if (xpn.get_byMem().isSame(mem)){
				allIncome.add(addIncome(xpn));
			}
		}
		return allIncome;
	}
	/**
	 * 
	 * @param mem
	 * @return Vector containing loans matching mem
	 * @Precondition updated managers
	 * @Postcondition 
	 */
	public Vector findLoanByMem(FamilyMember mem){
		Vector<Vector> allLoans = new Vector<Vector>();
		for(Loan xpn : _loan.getList())
		{
			if (xpn.get_byMem().isSame(mem)){
				allLoans.add(addLoan(xpn));
			}
		}
		return allLoans;
	}
	/**
	 * 
	 * @param mem
	 * @return Vector containing transactions matching mem
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findAllByMem(FamilyMember mem){
		Vector<Vector> allExpenses = new Vector<Vector>();
		String prefix = "-";
		String loanType;
		for(Expense xpn : _expense.getList())
		{
			if (xpn.get_byMem().isSame(mem)){
				allExpenses.add(addAll(xpn,"Expense", prefix));
			}
		}
		prefix = "+";
		for(Income xpn : _income.getList())
		{
			if (xpn.get_byMem().isSame(mem)){
				allExpenses.add(addAll(xpn,"Income", prefix));
			}
		}
		for(Loan xpn : _loan.getList())
		{
			switch(xpn.get_loanState()){
			case BORROWED:
				prefix = "+";
				loanType = LoanState.BORROWED.name();
				break;
			case LENT:
				prefix = "-";
				loanType = LoanState.LENT.name();
				break;
			case INVESTMENT:
				prefix = "";
				loanType = LoanState.INVESTMENT.name();
			}
			if (xpn.get_byMem().isSame(mem)){
				allExpenses.add(addAll(xpn,"Loan, "+xpn.get_loanState(), prefix));
			}
		}
		return allExpenses;	
	}
	/**
	 * 
	 * @param cat
	 * @return Vector containing expenses matching cat
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findByCategory(Category cat){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Expense xpn : _expense.getList())
		{
			if (xpn.get_category()==cat.get_id()){
				allExpenses.add(addExpense(xpn));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param pay
	 * @return Vector containing expenses matching pay
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findByPayment(PaymentMethod pay){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Expense xpn : _expense.getList())
		{
			if (xpn.get_paymentMethod().equals(pay)){
				allExpenses.add(addExpense(xpn));
			}
		}
		return allExpenses;
	}
	public Vector findLoanState(LoanState state){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Loan xpn : _loan.getList())
		{
			if (xpn.get_loanState().equals(state)){
				allExpenses.add(addLoan(xpn));
			}
		}
		return allExpenses;
	}

	/**
	 * 
	 * @param from
	 * @param to
	 * @return Vector containing expenses between from and to
	 * @Precondition  updated managers, input validated
	 * @Postcondition 
	 */
	public Vector findExpenseByDate(Date from, Date to){
		Vector<Vector> allExpenses = new Vector<Vector>();
		if (!to.isGreaterOrEqual(from))
			return allExpenses;
		for(Expense xpn : _expense.getList())
		{
			if (xpn.get_date().isGreaterOrEqual(from)&&to.isGreaterOrEqual(xpn.get_date())){
				allExpenses.add(addExpense(xpn));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param from
	 * @param to
	 * @return Vector containing incomes between from and to
	 * @Precondition  updated managers, validated inputs
	 * @Postcondition 
	 */
	public Vector findIncomeByDate(Date from, Date to){
		Vector<Vector> allIncome = new Vector<Vector>();
		if (!to.isGreaterOrEqual(from))
			return allIncome;
		for(Income xpn : _income.getList())
		{
			if (xpn.get_date().isGreaterOrEqual(from)&&to.isGreaterOrEqual(xpn.get_date())){
				allIncome.add(addIncome(xpn));
			}
		}
		return allIncome;
	}
	/**
	 * 
	 * @param from
	 * @param to
	 * @return Vector containing loans between from and to
	 * @Precondition  updated managers, validated inputs
	 * @Postcondition 
	 */
	public Vector findLoanByDate(Date from, Date to){
		Vector<Vector> allLoans = new Vector<Vector>();
		if (!to.isGreaterOrEqual(from))
			return allLoans;
		for(Loan loan : _loan.getList())
		{
			if (loan.get_date().isGreaterOrEqual(from)&&to.isGreaterOrEqual(loan.get_date())){
				allLoans.add(addLoan(loan));
			}
		}
		return allLoans;
	}
	/**
	 * 
	 * @param from
	 * @param to
	 * @return Vector containing transactions between from and to
	 * @Precondition  updated managers, validated inputs
	 * @Postcondition 
	 */
	public Vector findAllByDate(Date from, Date to){
		Vector<Vector> all = new Vector<Vector>();
		if (!to.isGreaterOrEqual(from))
			return all;
		String prefix = "-";
		String loanType;
		for(Expense xpn : _expense.getList())
		{
			if (xpn.get_date().isGreaterOrEqual(from)&&to.isGreaterOrEqual(xpn.get_date())){
				all.add(addAll(xpn,"Expense", prefix));
			}
		}
		prefix = "+";
		for(Income xpn : _income.getList())
		{
			if (xpn.get_date().isGreaterOrEqual(from)&&to.isGreaterOrEqual(xpn.get_date())){
				all.add(addAll(xpn,"Income", prefix));
			}
		}
		for(Loan xpn : _loan.getList())
		{
			switch(xpn.get_loanState()){
			case BORROWED:
				prefix = "+";
				loanType = LoanState.BORROWED.name();
				break;
			case LENT:
				prefix = "-";
				loanType = LoanState.LENT.name();
				break;
			case INVESTMENT:
				prefix = "";
				loanType = LoanState.INVESTMENT.name();
			}
			if (xpn.get_date().isGreaterOrEqual(from)&&to.isGreaterOrEqual(xpn.get_date())){
				all.add(addAll(xpn,"Loan, "+xpn.get_loanState(), prefix));
			}
		}
		return all;
	}
	/**
	 * 
	 * @param from
	 * @param to
	 * @return Vector containing loans between from and to
	 * @Precondition  updated managers, validated inputs
	 * @Postcondition 
	 */
	public Vector findDueDate(Date from, Date to){
		Vector<Vector> allLoans = new Vector<Vector>();
		if (!to.isGreaterOrEqual(from))
			return allLoans;
		for(Loan xpn : _loan.getList())
		{
			if (xpn.get_dueDate().isGreaterOrEqual(from)&&to.isGreaterOrEqual(xpn.get_dueDate())){
				allLoans.add(addLoan(xpn));
			}
		}
		return allLoans;
	}
	/**
	 * 
	 * @param name
	 * @return Vector containing expenses with name containing input
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findExpenseString(String name){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Expense xpn : _expense.getList())
		{
			if (xpn.get_name().toLowerCase().contains(name.toLowerCase())){
				allExpenses.add(addExpense(xpn));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param name
	 * @return Vector containing income with name containing input
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findIncomeString(String name){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Income xpn : _income.getList())
		{
			if (xpn.get_name().toLowerCase().contains(name.toLowerCase())){
				allExpenses.add(addIncome(xpn));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param name
	 * @return Vector containing loans with name containing input
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findLoanString(String name){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Loan xpn : _loan.getList())
		{
			if (xpn.get_name().toLowerCase().contains(name.toLowerCase())){
				allExpenses.add(addLoan(xpn));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param name
	 * @return Vector containing transactions with name containing input
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findAllString(String name){
		Vector<Vector> allExpenses = new Vector<Vector>();
		String prefix = "-";
		String loanType;
		for(Expense xpn : _expense.getList())
		{
			if (xpn.get_name().toLowerCase().contains(name.toLowerCase())){
				allExpenses.add(addAll(xpn,"Expense", prefix));
			}
		}
		prefix = "+";
		for(Income xpn : _income.getList())
		{
			if (xpn.get_name().toLowerCase().contains(name.toLowerCase())){
				allExpenses.add(addAll(xpn,"Income", prefix));
			}
		}
		for(Loan xpn : _loan.getList())
		{
			switch(xpn.get_loanState()){
			case BORROWED:
				prefix = "+";
				loanType = LoanState.BORROWED.name();
				break;
			case LENT:
				prefix = "-";
				loanType = LoanState.LENT.name();
				break;
			case INVESTMENT:
				prefix = "";
				loanType = LoanState.INVESTMENT.name();
			}
			if (xpn.get_name().toLowerCase().contains(name.toLowerCase())){
				allExpenses.add(addAll(xpn,"Loan, "+xpn.get_loanState(), prefix));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param name
	 * @return Vector containing expenses with paid to containing name
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findPaidTo(String name){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Expense xpn : _expense.getList())
		{
			if (xpn.get_partyInvolved().toLowerCase().contains(name.toLowerCase())){
				allExpenses.add(addExpense(xpn));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param name
	 * @return  Vector containing income with payers containing name
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findPayer(String name){
		Vector<Vector> allIncome = new Vector<Vector>();
		for(Income xpn : _income.getList())
		{
			if (xpn.get_partyInvolved().toLowerCase().contains(name.toLowerCase())){
				allIncome.add(addIncome(xpn));
			}
		}
		return allIncome;
	}
	/**
	 * 
	 * @param amount
	 * @param index
	 * @return Vector containing expenses meeting the condition for amount, also see compare()
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findExpenseAmount(double amount, int index){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Expense xpn : _expense.getList())
		{
			if (compare(xpn.get_amount(),amount,index)){
				allExpenses.add(addExpense(xpn));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param amount
	 * @param index
	 * @return Vector containing income meeting the condition for amount, also see compare()
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findIncomeAmount(double amount, int index){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Income xpn : _income.getList())
		{
			if (compare(xpn.get_amount(),amount,index)){
				allExpenses.add(addIncome(xpn));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param amount
	 * @param index
	 * @return Vector containing loans meeting the condition for amount, also see compare()
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findLoanAmount(double amount, int index){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Loan xpn : _loan.getList())
		{
			if (compare(xpn.get_amount(),amount,index)){
				allExpenses.add(addLoan(xpn));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param amount
	 * @param index
	 * @return Vector containing transactions meeting the condition for amount, also see compare()
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findAllAmount(double amount, int index){
		Vector<Vector> allExpenses = new Vector<Vector>();
		String prefix = "-";
		String loanType;
		for(Expense xpn : _expense.getList())
		{
			if (compare(xpn.get_amount(),amount,index)){
				allExpenses.add(addAll(xpn,"Expense", prefix));
			}
		}
		prefix = "+";
		for(Income xpn : _income.getList())
		{
			if (compare(xpn.get_amount(),amount,index)){
				allExpenses.add(addAll(xpn,"Income", prefix));
			}
		}
		for(Loan xpn : _loan.getList())
		{
			switch(xpn.get_loanState()){
			case BORROWED:
				prefix = "+";
				loanType = LoanState.BORROWED.name();
				break;
			case LENT:
				prefix = "-";
				loanType = LoanState.LENT.name();
				break;
			case INVESTMENT:
				prefix = "";
				loanType = LoanState.INVESTMENT.name();
			}
			if (compare(xpn.get_amount(),amount,index)){
				allExpenses.add(addAll(xpn,"Loan, "+xpn.get_loanState(), prefix));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param amount
	 * @param index
	 * @return Vector containing expenses meeting the condition for months left, also see compare()
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findMonthsLeft(double amount, int index){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Loan xpn : _loan.getList())
		{
			if (compare(xpn.get_monthsLeft(),amount,index)){
				allExpenses.add(addLoan(xpn));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param amount
	 * @param index
	 * @return Vector containing expenses meeting the condition for monthly payment, also see compare()
	 * @Precondition  updated managers
	 * @Postcondition 
	 */
	public Vector findMonthlyPayment(double amount, int index){
		Vector<Vector> allExpenses = new Vector<Vector>();
		for(Loan xpn : _loan.getList())
		{
			if (compare(xpn.get_paymentPerMonth(),amount,index)){
				allExpenses.add(addLoan(xpn));
			}
		}
		return allExpenses;
	}
	/**
	 * 
	 * @param xpn
	 * @return Vector which sequentially contains expense data
	 * @Precondition updated managers
	 * @Postcondition 
	 */
	private Vector addExpense(Expense xpn){
		Vector entry = new Vector();
		entry.add(_category.get(xpn.get_category()).get_name());
		entry.add(xpn.get_name());
		entry.add("$" + DataFormat.returnTwoDecimals(xpn.get_amount()));
		entry.add(xpn.get_partyInvolved());
		entry.add(xpn.get_paymentMethod());
		entry.add(xpn.get_frequency());
		entry.add("$" + DataFormat.returnTwoDecimals(xpn.get_totalAmount()));
		entry.add(xpn.get_date());
		entry.add(xpn.get_lastUpdateDate());
		entry.add(xpn.get_byMem());
		return entry;
	}
	/**
	 * 
	 * @param xpn
	 * @return Vector which sequentially contains income data
	 * @Precondition updated managers
	 * @Postcondition 
	 */
	private Vector addIncome(Income income){
		Vector entry = new Vector();
		entry.add(income.get_name());
		entry.add("$" + DataFormat.returnTwoDecimals(income.get_amount()));
		entry.add(income.get_partyInvolved());
		entry.add(income.get_frequency());
		entry.add("$" + DataFormat.returnTwoDecimals(income.get_totalAmount()));
		entry.add(income.get_date());
		entry.add(income.get_lastUpdateDate());
		entry.add(income.get_byMem());
		return entry;
	}
	/**
	 * 
	 * @param xpn
	 * @return Vector which sequentially contains loan data
	 * @Precondition updated managers
	 * @Postcondition 
	 */
	private Vector addLoan(Loan loan){
		Vector entry = new Vector();		
		entry.add(loan.get_name());
		entry.add("$" + DataFormat.returnTwoDecimals(loan.get_totalAmount()));
		entry.add("$" + DataFormat.returnTwoDecimals(loan.get_amount()));
		entry.add(loan.get_loanState());
		entry.add(loan.get_lastUpdateDate());
		entry.add(loan.get_partyInvolved());
		entry.add(loan.get_byMem());
		entry.add(DataFormat.returnTwoDecimals(loan.get_interestRate()) + "%");
		entry.add(loan.get_monthsLeft());
		entry.add("$" + DataFormat.returnTwoDecimals(loan.get_paymentPerMonth()));
		return entry;
	}
	/**
	 * 
	 * @param xpn
	 * @param type, refers to type of transaction
	 * @param prefix, + or - 
	 * @return Vector which sequentially contains transaction data
	 * @Precondition updated managers
	 * @Postcondition 
	 */
	private Vector addAll(Transaction xpn, String type, String prefix){
		Vector entry = new Vector();
		entry.add(xpn.get_name());
		entry.add(type);
		entry.add(prefix+"$"+DataFormat.returnTwoDecimals(xpn.get_amount()));
		entry.add(xpn.get_date());
		entry.add(xpn.get_byMem());
		return entry;
	}
	/**
	 * Selects a comparison between inputs x and y based on index
	 * @param x
	 * @param y
	 * @param index
	 * @return true if selected condition is met
	 * @Precondition 0<=index<=4
	 * @Postcondition 
	 */
	public boolean compare(double x, double y, int index){
		switch (index){
		case 0:
			if (x>y)
				return true;
			return false;
		case 1:
			if (x>=y)
				return true;
			return false;
		case 2:
			if (x==y)
				return true;
			return false;
		case 3:
			if (x<y)
				return true;
			return false;
		case 4:
			if (x<=y)
				return true;
			return false;
		default: return false;
		}
	}
}
